namespace AutoFormatter {
    
    
    // This class allows you to handle specific events on the settings class:
    //  The SettingChanging event is raised before a setting's value is changed.
    //  The PropertyChanged event is raised after a setting's value is changed.
    //  The SettingsLoaded event is raised after the setting values are loaded.
    //  The SettingsSaving event is raised before the setting values are saved.
    internal sealed partial class AFSettings {
        
        public AFSettings() {

            SetAllowed();
        }
     


        public ButtonMode ButtonStyle
        {
            get {return (ButtonMode)this.ButtonStyleIndex; }
        }

        public bool ButtonStyleHasCheckedMode
        {
            get
            {
                return ButtonStyle == ButtonMode.Checkbox || ButtonStyle == ButtonMode.Radio;
            }
        }

        public bool ButtonStyleHasSpans
        {
            get
            {
                return ButtonStyleHasCheckedMode || ButtonStyle== ButtonMode.TextOnly;
            }
        }

        public readonly BlockMode[] BlockModes = (BlockMode[])System.Enum.GetValues(typeof(BlockMode));
        public BlockMode StartAs
        {
            get {
                if (!Showblock) return BlockMode.Full;
                return (BlockMode)this.StartAsFlag; }
        }

        /// <summary>
        /// The index of the Start as mode inside the <see cref="AllowedModes"/>
        /// </summary>
        public int StartAsIndex
        {
            get { return System.Array.IndexOf<BlockMode>(BlockModes, StartAs); }
            set
            {
                StartAsFlag = (int)BlockModes[value];
            }
        }

        public int AllowedStartAsIndex
        {
            get
            {
                if (allowedcount == 0) return -1;
                int i = AllowedIndexOf(StartAs);
                if (i == -1) return 0;
                return i;
            }
        }
        public BlockMode AllowedStartAs
        {
            get { return allowedmodes[AllowedStartAsIndex]; }
        }

        /// <summary>
        /// Added for easy binding
        /// </summary>
        public string AllowedStartAsString
        {
            get { return AllowedStartAs.ToString(); }
        }

        public InputElement GetInputElement()
        {
            InputElement inp = new InputElement();
            inp.Type = ButtonStyle.ToString();
            return inp;
        }

        public Border GetBorder()
        {
            if (ShowBorder)
            {
                Border b = new Border();
                b.Style = BorderStyle;
                b.Width = (int)BorderWidth;
                b.Color = BorderColor;
                return b;
            }
            return null;
        }

        public bool UseFixedWidth
        {
            get { return UserSetFixedWidth || ButtonStyle == ButtonMode.Button; }
        }

        public bool ShowBorder { get { return Showblock && UseBorder; } }

        /// <summary>
        /// The end-line value that determines if the value-switchboxes should be
        /// shown at all
        /// </summary>
        public bool ShowSwitchModes
        {
            get { return AllowSwitchMode && allowedcount > 1; }
        }

        /// <summary>
        /// Where <see cref="AllowSizeChange"/> is the user setting, this property
        /// returns whether the cummalative settings allow the use of switch mode.
        /// See also <see cref="ShowSwitchModes"/> which also determines if there is
        /// a need to show (if only one mode is allowed, there is no real need ;-) )
        /// </summary>
        public bool AllowSwitchMode
        {
            get{return Showblock && AllowSizeChange;}
        }

        protected override void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "AllowedModesFlag":
                    SetAllowed();
                    break;
                default:
                    break;
            }
            base.OnPropertyChanged(sender, e);
        }

        void SetAllowed()
        {
            allowedcount = 0;
            int j = AllowedModesFlag;
            while (j > 0)
            {
                if ((j & 1) > 0) allowedcount++;
                j >>= 1;
            }

            allowedmodes= new BlockMode[allowedcount];
            int i = 0, flag = AllowedModesFlag;
            foreach (BlockMode bm in BlockModes)
            {
                if ((flag & (int)bm) > 0)
                    allowedmodes[i++] = bm;
            }
        }

        int allowedcount;
        /// <summary>
        /// The numbers of allowed modes to show
        /// </summary>
        public int AllowedModesCount
        {
            get
            {
                return allowedcount;
            }
        }

        BlockMode[] allowedmodes;
        public BlockMode[] AllowedModes
        {
            get
            {
                return allowedmodes;
            }
        }

        public int AllowedIndexOf(BlockMode bm)
        {
            return System.Array.IndexOf<BlockMode>(allowedmodes, bm);
        }

        public bool IsAllowed(BlockMode bm)
        {
            return ShowSwitchModes && ((int)bm & AllowedModesFlag) > 0;
        }

        public BorderStyles BorderStyle
        {
            get { return (BorderStyles)BorderStyleIndex; }
        }

        /// <summary>
        /// Each n-th step the progress is updated. As always, a lower value gives
        /// a more accurate progressbar, but slower performance and vice versa
        /// </summary>
        public const int ProgressUpdateStep = 10;
    }
}
